﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
using System;

public class SocketManager
{


    private static SocketManager instace;
    private Socket socketConnect;
    private Socket socketReceive;
    private Thread threadCnnect;
    private Thread threadReceive;

    //private string IP = "127.0.0.1";//"172.16.131.64";
    private string IP = "192.168.1.111";
    private string Point = "7878";//"8080";

    //public Queue<OrderBody> orderQueue = new Queue<OrderBody>();    //网络消息队列
    public List<OrderBody> orderQueue = new List<OrderBody>();      //网络消息队列

    public static SocketManager Instance
    {
        get
        {
            if (instace == null)
                instace = new SocketManager();
            return instace;
        }
    }


    public void StartConnect()
    {
        Loger.Special("SocketManager", "StartConnect");
        threadCnnect = new Thread(Connect);
        threadCnnect.Start();
        Loger.Special("SocketManager", "StartConnect--2");
    }


    private void Connect()
    {
        Loger.Special("SocketManager", "Connect");
        try
        {
            socketConnect = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            IPAddress ip = IPAddress.Parse(IP);
            IPEndPoint point = new IPEndPoint(ip, int.Parse(Point));
            socketConnect.Connect(point);
            Debug.Log("链接成功!!!,ip:" + IP + ",端口:" + Point);
            threadReceive = new Thread(Receive);
            threadReceive.Start();
        }
        catch (Exception e)
        {
            Debug.Log("Connect error:" + e);
        }
    }


    private void Receive()
    {
        while (true)
        {
            try
            {
                lock (orderQueue)
                {
                    ////把解析的消息添加到消息队列
                    //int headLength = 8;
                    //byte[] headBuffer = new byte[8];    //消息头
                    //while (headLength > 0)
                    //{
                    //    byte[] buffer = new byte[8];     //字节缓冲
                    //    int iByteLength = 0;            //本次接收到的消息长度
                    //    if (headBuffer.Length > buffer.Length)
                    //    {
                    //        //如果要接受的字节长度大于字节缓冲，则按字节缓冲接收
                    //        iByteLength = socketConnect.Receive(buffer, buffer.Length, 0);
                    //    }
                    //    else
                    //    {
                    //        //如果要接受的字节长度小于字节缓冲，则按接受的字节接收
                    //        iByteLength = socketConnect.Receive(buffer, headLength, 0);
                    //    }
                    //    buffer.CopyTo(headBuffer, headBuffer.Length - headLength);
                    //    headLength -= iByteLength;
                    //}
                    ////消息码
                    //byte[] bytes = new byte[4];
                    //Array.Copy(headBuffer, 0, bytes, 0, 4);
                    //int cmd = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(bytes, 0));
                    ////包体长度
                    //bytes = new byte[4];
                    //int BodyLength = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(bytes, 0));
                    ////接收消息体
                    //byte[] bodyBuffer = new byte[BodyLength];
                    //while (BodyLength > 0)
                    //{
                    //    byte[] buffer = new byte[BodyLength > 1024 ? 1024 : BodyLength];
                    //    int iByteLength = 0;            //本次接收到的消息长度
                    //    if (BodyLength > buffer.Length)
                    //    {
                    //        iByteLength = socketConnect.Receive(buffer, buffer.Length, 0);
                    //    }
                    //    else
                    //    {
                    //        iByteLength = socketConnect.Receive(buffer, BodyLength, 0);
                    //    }
                    //    buffer.CopyTo(bodyBuffer, bodyBuffer.Length - BodyLength);
                    //    BodyLength -= iByteLength;
                    //}
                    int headLength = 16;//8; //消息头长度
                    byte[] recHaeadBytes = new byte[headLength];
                    while (headLength > 0)
                    {
                        int iBytesHead = 0;             //本次接收到的消息长度
                        byte[] buffer = new byte[16];//byte[8];    //字节缓冲
                        if (headLength > buffer.Length)
                        {
                            //如果要接受的字节长度大于字节缓冲，则按字节缓冲接收
                            iBytesHead = socketConnect.Receive(buffer, buffer.Length, 0);
                        }
                        else
                        {
                            //如果要接受的字节长度小于字节缓冲，则按接受的字节接收
                            iBytesHead = socketConnect.Receive(buffer, headLength, 0);
                        }
                        //将接收到的字节数保存  
                        buffer.CopyTo(recHaeadBytes, recHaeadBytes.Length - headLength);
                        headLength -= iBytesHead;
                    }

                    //接收消息体
                    byte[] bytes = new byte[4];
                    Array.Copy(recHaeadBytes, 0, bytes, 0, 4);
                    int cmd = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(bytes, 0));
                    bytes = new byte[8];
                    Array.Copy(recHaeadBytes, 4, bytes, 0, 8);
                    long userId = IPAddress.NetworkToHostOrder(BitConverter.ToInt64(bytes, 0));
                    //消息体长度
                    bytes = new byte[4];
                    Array.Copy(recHaeadBytes, 12, bytes, 0, 4);
                    int BodyLength = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(bytes, 0));
                    //存储消息体字节
                    byte[] recBodyBuffer = new byte[BodyLength];
                    while (BodyLength > 0)
                    {
                        byte[] buffer = new byte[BodyLength > 1024 ? 1024 : BodyLength];  //字节缓冲
                        int iBytesHead = 0;             //本次接收到的消息长度
                        if (BodyLength > buffer.Length)
                        {
                            iBytesHead = socketConnect.Receive(buffer, buffer.Length, 0);
                        }
                        else
                        {
                            iBytesHead = socketConnect.Receive(buffer, BodyLength, 0);
                        }
                        //将接收到的字节数保存  
                        buffer.CopyTo(recBodyBuffer, recBodyBuffer.Length - BodyLength);
                        BodyLength -= iBytesHead;
                    }
                    OrderBody ob = new OrderBody();
                    ob.Cmd = cmd;
                    ob.BodyBuffer = recBodyBuffer;
                    Debug.Log("Receive=============cmd:" + cmd);
                    //Debug.Log("userId:" + userId);
                    if (Global.Instance.userId == 0)
                    {
                        Global.Instance.userId = userId;
                    }
                    orderQueue.Add(ob);
                }
            }
            catch (Exception e)
            {
                Debug.Log("Receive error:" + e);
                OnDestory();
            }
        }
    }


    public void BroadcastOrder()
    {
        //lock (orderQueue)
        //{
        //    if (orderQueue.Count > 0)
        //    {
        //        foreach (var order in orderQueue)
        //        {
        //            //派发消息
        //            this.Dispatch<byte[]>(order.Cmd, order.BodyBuffer);
        //        }
        //        orderQueue.Clear();
        //    }
        //}

        if (orderQueue.Count > 0)
        {
            foreach (var order in orderQueue)
            {
                //派发消息
                this.Dispatch<byte[]>(order.Cmd, order.BodyBuffer);
            }
            orderQueue.Clear();
        }
    }

    /// <summary>
    /// 派发消息给Lua
    /// </summary>
    public void BroadcastOrderByLua()
    {
        if (orderQueue.Count > 0)
        {
            foreach (var order in orderQueue)
            {
                //派发消息
                //this.Dispatch<byte[]>(order.Cmd, order.BodyBuffer);

            }
            orderQueue.Clear();
        }
    }


    /// <summary>
    /// 发送网络消息
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="cmd"></param>
    /// <param name="t"></param>
    public void SendNetMsg<T>(int cmd, T t)
    {
        OrderBody ob = new OrderBody();
        ob.Cmd = cmd;
        byte[] bytes = PBSerializer.NSerialize<T>(t);
        ob.BodyBuffer = bytes;
        //ServerConnect.Instance.SendMsgWithData(cmd, ob.byteBuffer);
        Send(ob);
    }


    public void SendNetMsg(int cmd,byte[] bytes)
    {
        OrderBody ob = new OrderBody();
        ob.Cmd = cmd;
        ob.UserId = Global.Instance.userId;
        ob.BodyBuffer = bytes;
        Send(ob);
    }


    private void Send(OrderBody ob)
    {
        byte[] totalByte = ob.GetNetBuffer();
        
        socketConnect.BeginSend(totalByte, 0, totalByte.Length, SocketFlags.None, asyncResult =>
           {
               int length = socketConnect.EndSend(asyncResult);
               Debug.Log("SendMessage---------->callback");
           }, null);
    }

    public void OnDestory()
    {
        Debug.Log("----OnDestory---------");
        if (threadCnnect != null)
        {
            threadCnnect.Abort();
            threadCnnect = null;
        }
        if (threadReceive != null)
        {
            threadReceive.Abort();
            threadReceive = null;
        }
        if (socketConnect != null)
        {
            socketConnect.Close();
            socketConnect = null;
        }
           
        if (socketReceive != null)
        {
            socketReceive.Close();
            socketReceive = null;
        }
          
    }

}
